﻿//------------------------------------------------------------------------------
//Author: Christoph van der Fecht
//CodePlex: http://www.codeplex.com/site/users/view/ChristophvdF
//
//Copyright(c) Christoph van der Fecht
//------------------------------------------------------------------------------
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using GalaSoft.MvvmLight;
using GalaSoft.MvvmLight.Command;
using GalaSoft.MvvmLight.Messaging;
using SerienNewsReader.Model;
using SerienNewsReaderMVVM;
using SerienNewsReaderMVVM.EventArguments;

namespace SerienNewsReader.ViewModel
{
    /// <summary>
    /// This class contains properties that a View can data bind to.
    /// <para>
    /// Use the <strong>mvvminpc</strong> snippet to add bindable properties to this ViewModel.
    /// </para>
    /// <para>
    /// You can also use Blend to data bind with the tool's support.
    /// </para>
    /// <para>
    /// See http://www.galasoft.ch/mvvm/getstarted
    /// </para>
    /// </summary>
    public class SeriesViewModel : ViewModelBase
    {
        /// <summary>
        /// Command for the resolution filter
        /// </summary>
        private RelayCommand resolutionFilterCommand = null;

        /// <summary>
        /// Contains all series that are dwnloaded
        /// </summary>
        private List<RSSFeed> allSeries = default(List<RSSFeed>);

        /// <summary>
        /// Holds the filterd list containing series of any resolution
        /// </summary>
        private List<RSSFeed> everyResolution = default(List<RSSFeed>);

        /// <summary>
        /// The <see cref="HDReader" /> property's name.
        /// </summary>
        public const string HDReaderPropertyName = "HDReader";

        /// <summary>
        /// Value of the <see cref="HDReadyFilter"/>
        /// </summary>
        private bool hdReady = false;

        /// <summary>
        /// The <see cref="FullHD" /> property's name.
        /// </summary>
        public const string FullHDPropertyName = "FullHD";

        /// <summary>
        /// Value for the <see cref="FullHDFilter"/>
        /// </summary>
        private bool fullHD = false;

        /// <summary>
        /// Series that are displayed
        /// </summary>
        private ObservableCollection<RSSFeed> series = default(ObservableCollection<RSSFeed>);

        /// <summary>
        /// Visibility of the progress bar
        /// </summary>
        private System.Windows.Visibility progressbarVisible = System.Windows.Visibility.Visible;

        /// <summary>
        /// Initializes a new instance of the SeriesViewModle class.
        /// </summary>
        public SeriesViewModel()
        {
            Messenger.Default.Register<string>(this, this.ApplySeriesTitleFilter);
            Messenger.Default.Register<string>(this, this.ApplyLanguageFilter); 

            if (IsInDesignMode)
            {
                List<RSSFeed> dummySeries = new List<RSSFeed>();
                for (int objectCounter = 0; objectCounter < 50; objectCounter++)
                {
                    dummySeries.Add(new RSSFeed("Test title", "Test Language", new System.Uri("http://www.test.cc")));
                }

                this.Series = new ObservableCollection<RSSFeed>(dummySeries);
            }
            else
            {
                Loader.Instance.DownloadCompleted += new Loader.DownloadCompletedDelegate(OnDownloadCompleted);
                Loader.Instance.LoadSeries();
            }
        }

        /// <summary>
        /// Receives the parsed result of the download
        /// </summary>
        /// <param name="sender">Object that sends the event</param>
        /// <param name="e">Instance of <see cref="DownloadFinishedEventArgs"/> containing the parsed series and movies</param>
        void OnDownloadCompleted(object sender, DownloadFinishedEventArgs e)
        {
            Loader.Instance.DownloadCompleted -= this.OnDownloadCompleted;
            if (e.Series != null)
            {
                this.allSeries = e.Series;
                this.everyResolution = this.allSeries;
                this.Series = new ObservableCollection<RSSFeed>(e.Series);
            }

            this.ProgressBarVisible = System.Windows.Visibility.Hidden;
        }

        /// <summary>
        /// Applyes the filter for the resolution, deppending on <see cref="HDReader"/> and <see cref="FullHD"/>
        /// </summary>
        private void ApplyResolutionFilter()
        {
            if (this.HDReader && this.FullHD)
            {
                this.Series = new ObservableCollection<RSSFeed>(
                    this.everyResolution.Where(x => x.Title.ToLower().Contains("720p") ||
                    x.Title.ToLower().Contains("1080p")));
            }
            else if (this.HDReader)
            {
                this.Series = new ObservableCollection<RSSFeed>(
                    this.everyResolution.Where(x => x.Title.ToLower().Contains("720p")));
            }
            else if (this.FullHD)
            {
                this.Series = new ObservableCollection<RSSFeed>(
                    this.everyResolution.Where(x => x.Title.ToLower().Contains("1080p")));
            }
            else
            {
                this.Series = new ObservableCollection<RSSFeed>(this.everyResolution);
            }
        }

        /// <summary>
        /// Filters the series by title
        /// </summary>
        /// <param name="criteria">Searchcriteria for the filter</param>
        private void ApplySeriesTitleFilter(string criteria)
        {
            if (string.IsNullOrEmpty(criteria))
            {
                return;
            }
            else
            {
                this.HDReader = false;
                this.FullHD = false;
                if (criteria.Equals("Deutsch") ||
                    criteria.Equals("Englisch"))
                {
                    return;
                }

                if (criteria.Equals("All my series"))
                {
                    this.ApplyFilterAllMySeries();
                }

                else if (criteria.Equals("All series"))
                {
                    this.everyResolution = this.allSeries;
                    this.Series = new ObservableCollection<RSSFeed>(this.allSeries);
                }

                else
                {
                    if (criteria.Contains('.'))
                    {
                        criteria = criteria.Replace('.', ' ');
                    }
                    criteria = criteria.ToLower();

                    List<RSSFeed> result = this.allSeries.Where(x => x.Title.ToLower().Contains(criteria)).OrderBy(
                        x => x.Title).ToList<RSSFeed>();

                    this.Series = new ObservableCollection<RSSFeed>(result);
                    this.everyResolution = result;
                }
            }
        }

        /// <summary>
        /// Displayes all series that are defined in the config file
        /// </summary>
        private void ApplyFilterAllMySeries()
        {
            List<string> allSeries = config.Default.Series.Split(';').ToList<string>();
            List<RSSFeed> allMySeries = new List<RSSFeed>();
            foreach (string entry in allSeries)
            {
                if (string.IsNullOrEmpty(entry))
                {
                    continue;
                }

                else
                {
                    allMySeries.AddRange(
                        this.allSeries.Where(x => x.Title.ToLower().Contains(entry.ToLower())).OrderBy(x => x.Title)
                        );
                }
            }

            if (allMySeries.Count > 0)
            {
                this.everyResolution = allMySeries;
                this.Series = new ObservableCollection<RSSFeed>(allMySeries);
            }
        }

        /// <summary>
        /// Filters the series by language
        /// </summary>
        /// <param name="language">Language to filter</param>
        private void ApplyLanguageFilter(string language)
        {
            if (!language.Equals("Deutsch") || !language.Equals("Englisch"))
            {
                return;
            }

            this.Series = new ObservableCollection<RSSFeed>(
                this.allSeries.Where(x => x.Language.ToLower().Equals(language.ToLower())));
        }

        /// <summary>
        /// Gets the command to apply the resolution filter
        /// </summary>
        public RelayCommand ResolutionFilterCommand
        {
            get
            {
                if (this.resolutionFilterCommand == null)
                {
                    this.resolutionFilterCommand = new RelayCommand(this.ApplyResolutionFilter);
                }
                return this.resolutionFilterCommand;
            }
        }

        /// <summary>
        /// Gets or sets the list of series to be displayed
        /// </summary>
        public ObservableCollection<RSSFeed> Series
        {
            get
            {
                return this.series;
            }
            set
            {
                if (value != this.series)
                {
                    this.series = new ObservableCollection<RSSFeed>(value.OrderBy(x => x.Title));

                    base.RaisePropertyChanged("Series");
                }
            }
        }
        
        /// <summary>
        /// Gets or sets the visible value of the <see cref="ProgressBar"/>
        /// </summary>
        public System.Windows.Visibility ProgressBarVisible
        {
            get
            {
                return this.progressbarVisible;
            }
            set
            {
                if (value != this.progressbarVisible)
                {
                    this.progressbarVisible = value;
                    base.RaisePropertyChanged("ProgressBarVisible");
                }
            }
        }

        /// <summary>
        /// Gets or sets the filter for HD ready (720p)
        /// </summary>
        public bool HDReader
        {
            get
            {
                return hdReady;
            }

            set
            {
                if (hdReady == value)
                {
                    return;
                }

                var oldValue = hdReady;
                hdReady = value;

                // Update bindings, no broadcast
                RaisePropertyChanged(HDReaderPropertyName);
            }
        }

        /// <summary>
        /// Gets or sets the filter for FullHD (1080p)
        /// </summary>
        public bool FullHD
        {
            get
            {
                return fullHD;
            }

            set
            {
                if (fullHD == value)
                {
                    return;
                }

                var oldValue = fullHD;
                fullHD = value;

                // Update bindings, no broadcast
                RaisePropertyChanged(FullHDPropertyName);
            }
        }

        /// <summary>
        /// Cleans the viewmodle
        /// </summary>
        public void Cleaup()
        {
            this.series = null;
            this.progressbarVisible = System.Windows.Visibility.Hidden;
            this.hdReady = false;
            this.fullHD = false;
            this.resolutionFilterCommand = null;
            Messenger.Default.Unregister<string>(this, this.ApplySeriesTitleFilter);
            Messenger.Default.Unregister<string>(this, this.ApplyLanguageFilter);

            base.Cleanup();
        }
    }
}